package com.weituotian.moudle.member.dao.impl;

import com.weituotian.core.jpa.domain.JPQLParamsSetter;
import com.weituotian.core.jpa.domain.Specification;
import com.weituotian.core.utils.DateUtil;
import com.weituotian.core.utils.DtoUtils;
import com.weituotian.core.utils.PageInfo;
import com.weituotian.moudle.member.dao.IVideoDao;
import com.weituotian.moudle.member.entity.*;
import com.weituotian.moudle.member.entity.enums.VideoState;
import com.weituotian.moudle.member.entity.vo.VideoListVo;
import com.weituotian.system.dao.impl.BaseDao;
import com.weituotian.system.entity.enums.OpenState;
import org.hibernate.Session;
import org.springframework.stereotype.Repository;

import javax.persistence.NoResultException;
import javax.persistence.Query;
import javax.persistence.Tuple;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.*;
import java.util.*;

/**
 * 视频Dao
 * Created by ange on 2017/2/22.
 */
@Repository
public class VideoDao extends BaseDao<Video, Integer> implements IVideoDao {

    @Override
    protected String getEntityName() {
        return "Video";
    }

    @Override
    protected String getIdFieldName() {
        return "id";
    }

    @Override
    public Video findOneFetch(Integer id) {
        //因为fetch = FetchType.LAZY,所以都用left join fetch了
        String jpql = "select video from Video video left join fetch video.member left join fetch video.partition left join fetch video.attachment where video.id=:id";
        Query query = getSession().createQuery(jpql);
        query.setParameter("id", id);
        try {
            return (Video) query.getSingleResult();
        } catch (NoResultException e) {
            return null;
        }
    }

    public List<VideoListVo> findPageMember(Integer memberId, String where1) {
//        return findPageMember(memberId, where1, null);
        return null;
    }

    @Override
    public List<VideoListVo> findPageMember(Integer memberId, String where1, PageInfo<?> pageInfo, JPQLParamsSetter setter) {
        String jpql = "select video, partition.name, member1.name, attachment.id from Video video left join video.member member1 left join video.partition partition left join video.attachment attachment where member1.id=:id1 and video.openState=:openState and " + where1;//

        Query query = getSession().createQuery(jpql)
                .setParameter("id1", memberId)
                .setParameter("openState", OpenState.OPEN);

        if (setter != null) {
            setter.onSetParams(query);
        }
        //分页
        query.setFirstResult(pageInfo.getFrom());
        query.setMaxResults(pageInfo.getPagesize());

        //结果list
        List list = query.getResultList();


        //总数
        String jpqlCount = "select count(*) from Video video left join video.member member1 left join video.partition partition left join video.attachment attachment where member1.id=:id1 and video.openState=:openState and " + where1;
        Query queryCount = getSession().createQuery(jpqlCount)
                .setParameter("id1", memberId)
                .setParameter("openState", OpenState.OPEN);
        if (setter != null) {
            setter.onSetParams(query);
        }
        Long total = (Long) queryCount.getSingleResult();
        pageInfo.setTotal(total.intValue());


        List<VideoListVo> vos = new ArrayList<>();
        for (Object row : list) {
            VideoListVo vo = new VideoListVo();

            Object[] cells = (Object[]) row;
//            VideoListVo vo = (VideoListVo) cells[0];
            //cells[0]是Video,1是后面的
            Video video = (Video) cells[0];
            DtoUtils.copyProperties(video, vo);

//            vo.setVideoState(video.getVideoState());
            vo.setPartitionName((String) cells[1]);
            vo.setMemberName((String) cells[2]);
            vo.setAttachmentId((Integer) cells[3]);

            vos.add(vo);
        }
        return vos;
    }

    @Override
    public List<VideoListVo> findLastest(PageInfo<VideoListVo> pageInfo) {
        Session session = getSession();

        CriteriaBuilder cb = session.getCriteriaBuilder();
        CriteriaQuery<Tuple> cq = cb.createQuery(Tuple.class);

        Root<Video> video = cq.from(Video.class);
        Join<Video, Partition> partition = video.join(Video_.partition, JoinType.LEFT);
        Join<Video, Member> member = video.join(Video_.member, JoinType.LEFT);
        Join<Video, Attachment> attachment = video.join(Video_.attachment, JoinType.LEFT);

        /*-----搜索条件构建-----*/
        List<Predicate> predicates = new ArrayList<Predicate>();

        //限定开启状态
        predicates.add(cb.equal(video.get(Video_.openState), OpenState.OPEN));
        predicates.add(cb.equal(video.get(Video_.videoState), VideoState.Audited));//审核通过的

        for (Map.Entry<String, Object> entry : pageInfo.getCondition().entrySet()) {
            String name = entry.getKey();
            String value = String.valueOf(entry.getValue());
            if (name.equals("name")) {
                predicates.add(cb.like(video.get("name"), "%" + value + "%"));
            } else if (name.equals("partition")) {
                predicates.add(cb.equal(partition.get(Partition_.id), value));
            } else if (name.equals("member")) {
                predicates.add(cb.equal(member.get(Member_.id), value));
            }
        }

        Predicate predicate = cb.and(predicates.toArray(new Predicate[predicates.size()]));
        if (predicate != null) {
            cq.where(predicate);
        }

        /* order 排序 */
        Map<String, String> sort = pageInfo.getOrderby();
        if (sort != null) {
            List<Order> orders = toOrders(sort, video, cb);
            cq.orderBy(orders);
        }

        /*-----select-----*/
        cq.select(cb.tuple(video, partition.get(Partition_.name), member.get(Member_.name)));

        TypedQuery<Tuple> query = session.createQuery(cq);

        //分页
        query.setFirstResult(pageInfo.getFrom());
        query.setMaxResults(pageInfo.getPagesize());

        List<Tuple> result = query.getResultList();

        /* 转换成vo */
        List<VideoListVo> vos = new ArrayList<>();
        for (Tuple tuple : result) {
            VideoListVo vo = new VideoListVo();

            Video video1 = tuple.get(0, Video.class);
            DtoUtils.copyProperties(video1, vo);

            vo.setPartitionName((String) tuple.get(1));
            vo.setMemberName((String) tuple.get(2));

            vos.add(vo);
        }

        return vos;
    }

    public List<VideoListVo> findLastest2(PageInfo<VideoListVo> pageInfo, Specification<Video> spec) {
        Session session = getSession();

        CriteriaBuilder cb = session.getCriteriaBuilder();
        CriteriaQuery<Tuple> cq = cb.createQuery(Tuple.class);

        Root<Video> video = cq.from(Video.class);

        /* where 条件 */
        Predicate predicate = spec.toPredicate(video, cq, cb);
        cq.where(predicate);

        /* order 排序 */
        Map<String, String> sort = pageInfo.getOrderby();
        if (sort != null) {
            List<Order> orders = toOrders(sort, video, cb);
            spec.onOrder(orders, video, cq, cb);
            cq.orderBy(orders);
        }

        /*-----select-----*/
        Path<Partition> partition = video.get(Video_.partition);
        Path<Member> member = video.get(Video_.member);
        cq.select(cb.tuple(video, partition.get(Partition_.name), member.get(Member_.name)));

        TypedQuery<Tuple> query = session.createQuery(cq);

        //分页
        query.setFirstResult(pageInfo.getFrom());
        query.setMaxResults(pageInfo.getPagesize());

        //总数
        Long total = executeCountQuery(getCountQuery(spec));
        pageInfo.setTotal(total.intValue());

        //结果list
//        List<Tuple> result = query.getResultList();
        List<Tuple> result = total > pageInfo.getFrom() ? query.getResultList() : Collections.<Tuple>emptyList();

        /* 转换成vo */
        List<VideoListVo> vos = new ArrayList<>();
        for (Tuple tuple : result) {
            VideoListVo vo = new VideoListVo();

            Video video1 = tuple.get(0, Video.class);
            DtoUtils.copyProperties(video1, vo);

            vo.setPartitionName((String) tuple.get(1));
            vo.setMemberName((String) tuple.get(2));

            vos.add(vo);
        }

        return vos;
    }

    @Override
    public List<Video> findByAttachmentId(Integer attachmentId) {
        String jpql = "select video from Video video  where video.attachment.id=:attachmentId";
        Query query = getSession().createQuery(jpql);
        query.setParameter("attachmentId", attachmentId);
        return (List<Video>) query.getResultList();
    }

    @Override
    public List<Video> findByTitle(String title) {
        String jpql = "select video from Video video  where video.title=:title";
        Query query = getSession().createQuery(jpql);
        query.setParameter("title", title);
        return (List<Video>) query.getResultList();
    }

    public Integer getMemberVideosCount(Integer memberId) {
        String jpql = "select count(video) from Video video where video.member.id=:id";
        Query query = getSession().createQuery(jpql);
        query.setParameter("id", memberId);
        Long count = (Long) query.getSingleResult();
        return count.intValue() ;
    }

    public Integer getMemberVideoCommentsCount(Integer memberId){
        String jpql = "select count (video1) from Video video1 left join video1.member member1 left join video1.comments comments where member1.id=:id";
        Query query = getSession().createQuery(jpql);
        query.setParameter("id", memberId);
        Long count = (Long) query.getSingleResult();
        return count.intValue() ;
    }

    public Integer getNewlyVideoCount() {
        String jpql = "select count (video1) from Video video1 where video1.createTime >:yesterday";
        org.hibernate.query.Query query = getSession().createQuery(jpql);
        Date date = new Date();
        Date yesterday = DateUtil.yesterday(date);
        query.setParameter("yesterday", yesterday);
        Long count = (Long) query.getSingleResult();
        return count.intValue() ;
    }
}
